#include "AEScriptEngine.hpp"
#include "AELogManager.hpp"

#include <cassert>

#include "add_on/scriptstdstring/scriptstdstring.h"
#include "add_on/scriptdictionary/scriptdictionary.h"
#include "add_on/scriptarray/scriptarray.h"
#include "add_on/scriptmath/scriptmath.h"
#include "add_on/scriptmath/scriptmathcomplex.h"

using namespace arete::io;

BEGIN_ARETE_NAMESPACE(scripting)

	AEScriptEngine::AEScriptEngine(void) :
	m_engine(NULL),
	m_gc_interval(20.0f)
{
}

AEScriptEngine::~AEScriptEngine(void)
{
	m_engine->Release();
	m_engine = NULL;
}

void AEScriptEngine::initialize(void)
{
	AELogManager::log(ELL_NONE,"*****************************************");
	AELogManager::log(ELL_NONE,"*** --- Initializing Angelscript  --- ***");
	AELogManager::log(ELL_NONE,"*****************************************");

	m_engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	int r = m_engine->SetMessageCallback(asMETHOD(AEScriptEngine,messageCallback),this,asCALL_THISCALL); assert(r >= 0);

	RegisterStdString(m_engine);
	RegisterScriptArray(m_engine,true);
	RegisterStdStringUtils(m_engine);

	RegisterScriptDictionary(m_engine);
	RegisterScriptMath(m_engine);
	RegisterScriptMathComplex(m_engine);
}

void AEScriptEngine::messageCallback(const asSMessageInfo& _msg)
{
	std::stringstream s;
	s << _msg.section << " (" << _msg.row << ", " << _msg.col << ") : " << _msg.message;

	if(_msg.type == asMSGTYPE_ERROR) {
		AELogManager::log(ELL_ERROR,s.str());
	} else if(_msg.type == asMSGTYPE_WARNING) {
		AELogManager::log(ELL_WARN,s.str());
	} else if(_msg.type == asMSGTYPE_INFORMATION) {
		AELogManager::log(ELL_INFO,s.str());
	}
}

void AEScriptEngine::update(float _delta)
{
	m_engine->GarbageCollect(asGC_ONE_STEP);
}

asIScriptEngine* AEScriptEngine::getScriptEngine( void )
{
	return m_engine;
}

const float& AEScriptEngine::getGCInterval( void )
{
	return m_gc_interval;
}

END_ARETE_NAMESPACE